package com.lncg.service.impl;

import com.lncg.service.ITcpConnectionService;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * TCP连接管理服务实现类
 */
@Service
public class TcpConnectionServiceImpl implements ITcpConnectionService {

    private static final Logger logger = LoggerFactory.getLogger(TcpConnectionServiceImpl.class);

    /**
     * TCP客户端连接映射表
     * Key: "IP:PORT" 格式的客户端标识
     * Value: 对应的Netty ChannelHandlerContext
     */
    private final ConcurrentHashMap<String, ChannelHandlerContext> clientConnections = new ConcurrentHashMap<>();

    @Override
    public void addConnection(String clientKey, Object ctx) {
        if (ctx instanceof ChannelHandlerContext) {
            clientConnections.put(clientKey, (ChannelHandlerContext) ctx);
        }
    }

    @Override
    public void removeConnection(String clientKey) {
        ChannelHandlerContext removed = clientConnections.remove(clientKey);
        if (removed != null) {
            logger.info("移除TCP连接: {}, 当前连接数: {}", clientKey, clientConnections.size());
        } else {
            logger.debug("尝试移除不存在的TCP连接: {}", clientKey);
        }
    }

    @Override
    public boolean sendDataToClient(String clientIp, int clientPort, String data) {
        try {
            String clientKey = clientIp + ":" + clientPort;
            ChannelHandlerContext ctx = clientConnections.get(clientKey);

            if (ctx == null || !ctx.channel().isActive()) {
                logger.warn("TCP客户端连接不存在或已断开: {}", clientKey);
                return false;
            }

            // 将十六进制字符串转换为字节数组
            byte[] dataBytes = hexToBytes(data);

            // 通过Netty Channel发送数据给TCP客户端
            ctx.writeAndFlush(ctx.alloc().buffer(dataBytes.length).writeBytes(dataBytes));

            logger.info("数据已发送给TCP客户端: {}, 数据: {}", clientKey, data);
            return true;

        } catch (Exception e) {
            logger.error("发送数据给TCP客户端失败: {}:{}, 错误: {}", clientIp, clientPort, e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean sendDataToClient(String clientIp, int clientPort, byte[] data) {
        try {
            String clientKey = clientIp + ":" + clientPort;
            ChannelHandlerContext ctx = clientConnections.get(clientKey);

            if (ctx == null || !ctx.channel().isActive()) {
                logger.warn("TCP客户端连接不存在或已断开: {}", clientKey);
                return false;
            }

            // 通过Netty Channel发送字节数组数据给TCP客户端
            ctx.writeAndFlush(ctx.alloc().buffer(data.length).writeBytes(data));

            logger.info("字节数组数据已发送给TCP客户端: {}, 数据长度: {} 字节", clientKey, data.length);
            // 调试日志移除
            return true;

        } catch (Exception e) {
            logger.error("发送字节数组数据给TCP客户端失败: {}:{}, 错误: {}", clientIp, clientPort, e.getMessage(), e);
            return false;
        }
    }

    @Override
    public int getConnectionCount() {
        return clientConnections.size();
    }

    /**
     * 获取所有连接映射表
     * 用于连接健康检查和清理任务
     * @return 所有连接的映射表
     */
    public Map<String, ChannelHandlerContext> getAllConnections() {
        return new ConcurrentHashMap<>(clientConnections);
    }

    /**
     * 连接健康检查
     * 检查所有连接的健康状态并清理无效连接
     */
    public void healthCheckConnections() {
        int activeConnections = 0;
        int inactiveConnections = 0;
        
        for (Map.Entry<String, ChannelHandlerContext> entry : clientConnections.entrySet()) {
            String clientKey = entry.getKey();
            ChannelHandlerContext ctx = entry.getValue();
            
            if (ctx != null && ctx.channel().isActive()) {
                activeConnections++;
            } else {
                inactiveConnections++;
                // 移除无效连接
                clientConnections.remove(clientKey);
                logger.debug("健康检查发现并移除无效连接: {}", clientKey);
            }
        }
        
        if (inactiveConnections > 0) {
            logger.info("连接健康检查完成 - 活跃连接: {}, 清理无效连接: {}, 当前总连接数: {}", 
                activeConnections, inactiveConnections, clientConnections.size());
        }
    }

    @Override
    public boolean isConnectionActive(String clientIp, int clientPort) {
        String clientKey = clientIp + ":" + clientPort;
        ChannelHandlerContext ctx = clientConnections.get(clientKey);
        return ctx != null && ctx.channel().isActive();
    }

    @Override
    public boolean closeConnection(String clientIp, int clientPort) {
        try {
            String clientKey = clientIp + ":" + clientPort;
            ChannelHandlerContext ctx = clientConnections.get(clientKey);

            if (ctx == null) {
                logger.warn("TCP客户端连接不存在，无法关闭: {}", clientKey);
                return false;
            }

            if (!ctx.channel().isActive()) {
                logger.warn("TCP客户端连接已断开，无需关闭: {}", clientKey);
                // 从连接映射中移除
                clientConnections.remove(clientKey);
                return true;
            }

            // 关闭连接
            ctx.close();
            
            // 从连接映射中移除
            clientConnections.remove(clientKey);
            
            logger.info("TCP客户端连接已关闭: {}, 当前连接数: {}", clientKey, clientConnections.size());
            return true;

        } catch (Exception e) {
            logger.error("关闭TCP客户端连接失败: {}:{}, 错误: {}", clientIp, clientPort, e.getMessage(), e);
            return false;
        }
    }

    /**
     * 16进制转字节数组
     */
    private byte[] hexToBytes(String hex) {
        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                                 + Character.digit(hex.charAt(i+1), 16));
        }
        return data;
    }

    /**
     * 字节数组转16进制字符串
     */
    private String bytesToHex(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (byte b : bytes) {
            result.append(String.format("%02X", b & 0xFF));
        }
        return result.toString();
    }
}
